package SeedBank
//d
import org.springframework.dao.DataIntegrityViolationException

/**
 * This class provides functionality to the application regarding the class User.
 * 
 * @author Vikram
 *
 */
class UserController {
	
	def scaffold = true
	
    static allowedMethods = [save: "POST", update: "POST", delete: "POST"]
	
	/**
	 * Executed when a user hits the unlock page. It is left empty.
	 * 
	 */
	
	def unlock = {}
	
	/**
	* Executed when an administrator performs the unlock action on another user.
	*
	*/
	
	def unlocker = {
		def toUnlock = User.findByLogin(params.login)

		if(session.user && session.user.isAdmin()){
			if(toUnlock==null){
				flash.message = "User doesn't exist."
				redirect(controller:"User", action:"unlock")

			}else{
				toUnlock.lockCount = 0;
				flash.message = "${toUnlock.login} has been unlocked successfully!"
				redirect(controller:"User", action:"unlock")
			}
				
		}else{
			flash.message = "You don't have the rights to unlock an account, sorry."
			redirect(controller:"User", action:"unlock")
		}
	}
	
	/**
	* Executed when a user hits the login page. It is left empty.
	*
	*/
	
	def login = {}
	
	/**
	* Executed when a user performs a logout action.
	*
	*/
	
	def logout = {
		flash.message = "Goodbye ${session.user.login}"
		session.user = null
		redirect(action:"login")
	}
	
	/**
	* Executed when a user tries to login. Authenticate decides whether the user's 
	* entered credentials belong to a valid user.
	*
	*/
	
	def authenticate = {
		
		def user = User.findByLoginAndHashedPass(params.login, params.password.encodeAsSHA())
		def toLock = User.findByLogin(params.login)
		
		if( toLock?.lockCount>=3){
			flash.message = "Your locked for three bad attempts!"
			redirect(controller:"User", action:"login")
		}else if(user){
			session.user = user
			flash.message = "Welcome, ${user.login}!"
			user.lockCount = 0;
			redirect(controller:"Seed", action:"list")
		}else{
			flash.message = "Sorry, invalid login information."
			if(toLock && !toLock.isAdmin()){
				toLock.lockCount++
			}
			redirect(action:"login")
		}
		
	}
	
	/**
	* Executed when a user hits the index page. Redirect to the user list.
	*
	*/
	
    def index() {
        redirect(action: "list", params: params)
    }
	
	/**
	* Makes sure that the user trying to access this action is an admin. Only admins
	* can view the list of users.
	*
	*/
	
    def list() {
		if(session?.user?.admin){
			params.max = Math.min(params.max ? params.int('max') : 10, 100)
			[userInstanceList: User.list(params), userInstanceTotal: User.count()]
		}else{
			flash.message = "You do not have rights to view the list of users, sorry."
			redirect(uri: "/")
		}
        
    }
	
	/**
	 * Creates a new instance of User.
	 * @return
	 */
    def create() {
        [userInstance: new User(params)]
    }
	
	/**
	 * Saves this user to the database.
	 * @return
	 */
    def save() {
        def userInstance = new User(params)
        if (!userInstance.save(flush: true)) {
            render(view: "create", model: [userInstance: userInstance])
            return
        }

		flash.message = message(code: 'default.created.message', args: [message(code: 'user.label', default: 'User'), userInstance.id])
        redirect(action: "show", id: userInstance.id)
    }
	
	/**
	 * Accesses this user from the database.
	 * @return
	 */
    def show() {
        def userInstance = User.get(params.id)
		
        if (!userInstance) {
			flash.message = message(code: 'default.not.found.message', args: [message(code: 'user.label', default: 'User'), params.id])
            redirect(action: "list")
            return
        }

        [userInstance: userInstance]
    }
	
	/**
	 * Edits this user.
	 * @return
	 */
    def edit() {
        def userInstance = User.get(params.id)
		
		if(session.user?.id.equals(userInstance.id)){
			if (!userInstance) {
				flash.message = message(code: 'default.not.found.message', args: [message(code: 'user.label', default: 'User'), params.id])
				redirect(action: "list")
				return
			}
	
			[userInstance: userInstance]
		}else{
			flash.message = "Not your account, cant do that!"
			redirect(action: "show", id: params.id)
		}
        
    }
	
	/**
	 * update's this user's data in the database.
	 * @return
	 */
    def update() {
        def userInstance = User.get(params.id)
	
        if (!userInstance) {
            flash.message = message(code: 'default.not.found.message', args: [message(code: 'user.label', default: 'User'), params.id])
            redirect(action: "list")
            return
        }

        if (params.version) {
            def version = params.version.toLong()
            if (userInstance.version > version) {
                userInstance.errors.rejectValue("version", "default.optimistic.locking.failure",
                          [message(code: 'user.label', default: 'User')] as Object[],
                          "Another user has updated this User while you were editing")
                render(view: "edit", model: [userInstance: userInstance])
                return
            }
        }

        userInstance.properties = params

        if (!userInstance.save(flush: true)) {
            render(view: "edit", model: [userInstance: userInstance])
            return
        }
		
		if(userInstance && userInstance.confirmPassword.equals(userInstance.password) && !userInstance.password.equals(".")){
			userInstance.hashedPass = userInstance.password.encodeAsSHA()
			userInstance.password = "."
			userInstance.confirmPassword = "."
		}else{
			flash.message = "Passwords didn't match!"
			redirect(action: "edit", id: userInstance.id)
		}
		
		flash.message = message(code: 'default.updated.message', args: [message(code: 'user.label', default: 'User'), userInstance.id])
        redirect(action: "show", id: userInstance.id)
    }
	
	/**
	 * Deletes this user from the database.
	 * @return
	 */
    def delete() {
        def userInstance = User.get(params.id)
		
		if(session.user?.id.equals(userInstance.id)){
			
			if (!userInstance) {
				flash.message = message(code: 'default.not.found.message', args: [message(code: 'user.label', default: 'User'), params.id])
				redirect(action: "list")
				return
			}
	
			try {
				userInstance.delete(flush: true)
				flash.message = message(code: 'default.deleted.message', args: [message(code: 'user.label', default: 'User'), params.id])
				redirect(action: "list")
			}
			catch (DataIntegrityViolationException e) {
				flash.message = message(code: 'default.not.deleted.message', args: [message(code: 'user.label', default: 'User'), params.id])
				redirect(action: "show", id: params.id)
			}
		}else{
			flash.message = "Not your account, cant do that!"
			redirect(action: "show", id: params.id)
		}
		
    }
}
